package com.fx.zmlzml.util;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;

/**
 * JWT工具类
 * 基于jjwt 0.11.x版本
 */
public class JwtUtil {

    // 默认密钥（生产环境请从配置文件读取）
    private static final String DEFAULT_SECRET = "MyJwtSecretKeyForSigningTokens1234567890123456";

    // 默认过期时间：7天
    private static final long DEFAULT_EXPIRE = 7 * 24 * 60 * 60 * 1000L;

    // Token前缀
    private static final String TOKEN_PREFIX = "Bearer ";

    // 签发者
    private static final String ISSUER = "zmlzml";

    private JwtUtil() {
        // 工具类，防止实例化
    }

    /**
     * 生成SecretKey
     */
    private static SecretKey generateSecretKey(String secret) {
        byte[] keyBytes = Decoders.BASE64.decode(secret);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 生成安全的密钥（Base64编码）
     */
    public static String generateSafeSecret() {
        return Encoders.BASE64.encode(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded());
    }

    /**
     * 生成JWT Token（使用默认配置）
     */
    public static String generateToken(String subject) {
        return generateToken(subject, new HashMap<>());
    }

    /**
     * 生成JWT Token（带自定义声明）
     */
    public static String generateToken(String subject, Map<String, Object> claims) {
        return generateToken(subject, claims, DEFAULT_EXPIRE);
    }

    /**
     * 生成JWT Token（自定义过期时间）
     */
    public static String generateToken(String subject, Map<String, Object> claims, long expire) {
        Date now = new Date();
        Date expireDate = new Date(now.getTime() + expire);

        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuer(ISSUER)
                .setIssuedAt(now)
                .setExpiration(expireDate)
                .signWith(generateSecretKey(DEFAULT_SECRET), SignatureAlgorithm.HS256)
                .compact();
    }

    /**
     * 生成带前缀的Token
     */
    public static String generateTokenWithPrefix(String subject, Map<String, Object> claims, long expire) {
        return TOKEN_PREFIX + generateToken(subject, claims, expire);
    }

    /**
     * 解析Token
     */
    public static Claims parseToken(String token) {
        if (token.startsWith(TOKEN_PREFIX)) {
            token = token.substring(TOKEN_PREFIX.length());
        }

        return Jwts.parserBuilder()
                .setSigningKey(generateSecretKey(DEFAULT_SECRET))
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 验证Token是否有效
     */
    public static boolean validateToken(String token) {
        try {
            if (token.startsWith(TOKEN_PREFIX)) {
                token = token.substring(TOKEN_PREFIX.length());
            }

            Jwts.parserBuilder()
                    .setSigningKey(generateSecretKey(DEFAULT_SECRET))
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (ExpiredJwtException e) {
            System.err.println("Token已过期: " + e.getMessage());
        } catch (UnsupportedJwtException e) {
            System.err.println("不支持的Token: " + e.getMessage());
        } catch (MalformedJwtException e) {
            System.err.println("Token格式错误: " + e.getMessage());
        } catch (SignatureException e) {
            System.err.println("Token签名错误: " + e.getMessage());
        } catch (IllegalArgumentException e) {
            System.err.println("Token参数错误: " + e.getMessage());
        } catch (Exception e) {
            System.err.println("Token验证失败: " + e.getMessage());
        }
        return false;
    }

    /**
     * 从Token中获取主题
     */
    public static String getSubject(String token) {
        return parseToken(token).getSubject();
    }

    /**
     * 从Token中获取指定声明
     */
    public static Object getClaim(String token, String claimName) {
        return parseToken(token).get(claimName);
    }

    /**
     * 获取Token中的所有声明
     */
    public static Map<String, Object> getAllClaims(String token) {
        return new HashMap<>(parseToken(token));
    }

    /**
     * 获取Token过期时间
     */
    public static Date getExpiration(String token) {
        return parseToken(token).getExpiration();
    }

    /**
     * 检查Token是否过期
     */
    public static boolean isTokenExpired(String token) {
        return getExpiration(token).before(new Date());
    }

    /**
     * 刷新Token（使用原有声明重新生成）
     */
    public static String refreshToken(String token, long newExpire) {
        Claims claims = parseToken(token);
        String subject = claims.getSubject();
        claims.remove("iat");
        claims.remove("exp");
        claims.remove("iss");

        return generateToken(subject, claims, newExpire);
    }

    /**
     * 获取剩余有效时间（毫秒）
     */
    public static long getRemainingTime(String token) {
        Date expiration = getExpiration(token);
        return expiration.getTime() - System.currentTimeMillis();
    }
}
